﻿#region Using directives

using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Text;
using System.Reflection;

#endregion

namespace WinTestBinding
{

    public class SearchableSortableBindingList<T> : BindingList<T>
    {
        #region Sort
        protected override bool SupportsSortingCore
        {
            get { return true; }
        }


        public void ForcedSort()
        {
            if(m_SortProperty != null)
            ApplySortCore(m_SortProperty,m_Direction);
        }
        protected override void ApplySortCore(PropertyDescriptor property, ListSortDirection direction)
        {
            PropertyDescriptor nProperty = property;
            if (property.Name.StartsWith("f"))
            {
                PropertyDescriptorCollection tmpP = TypeDescriptor.GetProperties(typeof(T));
                for (int i = 0; i < tmpP.Count; i++)
                {
                    if (tmpP[i].Name == property.Name.Replace("f", ""))
                    {
                        nProperty = tmpP[i];
                        break;
                    }
                }
            }
            List<T> items = this.Items as List<T>;
            m_IsSorted = false;
            if (items != null)
            {
                PropertyComparer<T> pc = new PropertyComparer<T>(nProperty, direction);
                items.Sort(pc);
                m_SortProperty = property;
                m_Direction = direction;
                m_IsSorted = true;
            }
           
            this.OnListChanged(new ListChangedEventArgs(ListChangedType.Reset, -1));
        }

       /* protected override void OnListChanged(ListChangedEventArgs e)
        {

        }*/
        protected override void RemoveSortCore()
        {
            m_IsSorted = false;
            m_SortProperty = null;   
        }

        private bool m_IsSorted;
        private ListSortDirection m_Direction = ListSortDirection.Ascending;
        private PropertyDescriptor m_SortProperty;

        protected override bool IsSortedCore
        {
            get { return m_IsSorted; }
        }
        protected override ListSortDirection SortDirectionCore
        {
            get
            {
                return m_Direction;
            }
        }
        protected override PropertyDescriptor SortPropertyCore
        {
            get
            {
                return m_SortProperty;
            }
        }
        #endregion

        #region Search
        protected override bool SupportsSearchingCore
        {
            get{return true;}
        }
        protected override int FindCore(PropertyDescriptor prop, object key)
        {
            List<T> items = this.Items as List<T>;
            if (items == null)
                return -1;

            foreach (T item in items)
            {
                string value = item.GetType().GetProperty(prop.Name).GetValue(item, null).ToString();
                bool bTrouve = false;
                switch (SearchMode)
                {
                    case StringSearchMode.Exact:
                        bTrouve = (value == key.ToString());
                        break;
                    case StringSearchMode.Contains:
                        bTrouve = (value.IndexOf(key.ToString(), SearchComparison)>=0);
                        break;
                    case StringSearchMode.EndsWith:
                        bTrouve = (value.EndsWith(key.ToString(), SearchComparison));
                        break;
                    case StringSearchMode.StartsWith:
                        bTrouve = (value.StartsWith(key.ToString(), SearchComparison));
                        break;
                }
                if (bTrouve)
                    return this.IndexOf(item);
            }
            return -1;
        }

        private StringSearchMode m_SearchMode = StringSearchMode.Exact;
        private StringComparison m_SearchComparison;

        public StringSearchMode SearchMode
        {
            get { return m_SearchMode; }
            set { m_SearchMode = value; }
        }
        public StringComparison SearchComparison
        {
            get { return m_SearchComparison; }
            set { m_SearchComparison = value; }
        }
        #endregion

    }
}
